package cn.heyige.backend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.heyige.backend.dto.ChatHistoryDto;
import cn.heyige.backend.entity.ChatHistoryDO;
import cn.heyige.backend.exception.BusinessException;
import cn.heyige.backend.exception.ErrorCode;
import cn.heyige.backend.mapper.ChatHistoryMapper;
import cn.heyige.backend.service.ChatHistoryService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 聊天历史服务实现类 - 精简版
 *
 * 专注于核心聊天历史管理功能，提高系统性能和可维护性
 * 增强数据验证和错误处理
 *
 * @author CodeBuddy
 */
@Slf4j
@Service("chatHistoryService")
@RequiredArgsConstructor
public class ChatHistoryServiceImpl extends ServiceImpl<ChatHistoryMapper, ChatHistoryDO> implements ChatHistoryService {

    private final ChatHistoryMapper chatHistoryMapper;
    
    private static final int DEFAULT_PAGE_SIZE = 20;
    private static final int MAX_PAGE_SIZE = 100;
    private static final String SESSION_PREFIX = "session_";

    /**
     * 保存聊天记录
     *
     * @param userId    用户ID
     * @param role      角色
     * @param content   内容
     * @param model     模型
     * @param tokens    token数量
     * @param sessionId 会话ID
     * @return 聊天记录
     */
    @Transactional(rollbackFor = Exception.class)
    public ChatHistoryDO saveChatHistory(Integer userId, String role, String content, String model, Integer tokens, String sessionId) {
        // 参数校验
        if (userId == null) {
            throw new IllegalArgumentException("用户ID不能为空");
        }

        if (!StringUtils.hasText(role)) {
            throw new IllegalArgumentException("角色不能为空");
        }

        if (!StringUtils.hasText(content)) {
            throw new IllegalArgumentException("内容不能为空");
        }

        try {
            ChatHistoryDO chatHistoryDO = new ChatHistoryDO();
            chatHistoryDO.setUserId(userId);
            chatHistoryDO.setRole(role);
            chatHistoryDO.setContent(content);
            chatHistoryDO.setModel(model);
            chatHistoryDO.setTokens(tokens != null ? tokens : 0);
            
            // 如果没有提供会话ID，则生成一个新的
            if (!StringUtils.hasText(sessionId)) {
                sessionId = generateSessionId();
            }
            chatHistoryDO.setSessionId(sessionId);
            chatHistoryMapper.insert(chatHistoryDO);
            log.debug("保存聊天记录: 用户 {}, 角色 {}, 内容长度 {}, 模型 {}", userId, role, content.length(), model);
            return chatHistoryDO;
        } catch (Exception e) {
            log.error("保存聊天记录失败: userId={}, role={}, contentLength={}",
                    userId, role, content != null ? content.length() : 0, e);
            throw new RuntimeException("保存聊天记录失败: " + e.getMessage());
        }
    }

    /**
     * 保存用户消息
     *
     * @param userId    用户ID
     * @param content   内容
     * @param model     模型
     * @param sessionId 会话ID
     * @return 聊天记录
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ChatHistoryDO saveUserMessage(Integer userId, String content, String model, String sessionId) {
        return saveChatHistory(userId, ChatHistoryDO.Role.USER.name(), content, model, 0, sessionId);
    }

    /**
     * 保存助手消息
     *
     * @param userId    用户ID
     * @param content   内容
     * @param model     模型
     * @param tokens    token数量
     * @param sessionId 会话ID
     * @return 聊天记录
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ChatHistoryDO saveAssistantMessage(Integer userId, String content, String model, Integer tokens, String sessionId) {
        return saveChatHistory(userId, ChatHistoryDO.Role.ASSISTANT.name(), content, model, tokens, sessionId);
    }

    /**
     * 保存系统消息
     *
     * @param userId    用户ID
     * @param content   内容
     * @param sessionId 会话ID
     * @return 聊天记录
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ChatHistoryDO saveSystemMessage(Integer userId, String content, String sessionId) {
        return saveChatHistory(userId, ChatHistoryDO.Role.SYSTEM.name(), content, null, 0, sessionId);
    }

    /**
     * 获取用户的聊天历史列表
     *
     * @param userId   用户ID
     * @param pageNum  分页参数
     * @param pageSize 分页参数
     * @return 聊天历史列表
     */
    public IPage<ChatHistoryDto.ChatHistoryResponse> getUserChatHistory(Integer userId, Integer pageNum, Integer pageSize) {
        // 参数校验
        if (userId == null) {
            throw new IllegalArgumentException("用户ID不能为空");
        }

        // 设置默认分页参数
        int actualPageNum = pageNum != null ? pageNum : 1;
        int actualPageSize = pageSize != null ? Math.min(pageSize, MAX_PAGE_SIZE) : DEFAULT_PAGE_SIZE;

        try {
            Page<ChatHistoryDO> chatHistories = chatHistoryMapper.selectPage(new Page<>(actualPageNum, actualPageSize),
                    new LambdaQueryWrapper<ChatHistoryDO>().eq(ChatHistoryDO::getUserId, userId)
                            .eq(ChatHistoryDO::getIsDeleted, false)
                            .orderByDesc(ChatHistoryDO::getCreateTime)
            );
            return chatHistories.convert(this::buildChatHistoryResponse);
        } catch (Exception e) {
            log.error("获取用户聊天历史失败: userId={}, pageNum={}, pageSize={}",
                    userId, actualPageNum, actualPageSize, e);
            throw new RuntimeException("获取用户聊天历史失败: " + e.getMessage());
        }
    }

    /**
     * 根据会话ID获取聊天历史列表
     *
     * @param userId    用户ID
     * @param sessionId 会话ID
     * @param pageNum   分页参数
     * @param pageSize  分页参数
     * @return 聊天历史列表
     */
    public IPage<ChatHistoryDto.ChatHistoryResponse> getChatHistoryBySession(Integer userId, String sessionId, Integer pageNum, Integer pageSize) {
        // 参数校验
        if (userId == null) {
            throw new IllegalArgumentException("用户ID不能为空");
        }

        if (!StringUtils.hasText(sessionId)) {
            throw new IllegalArgumentException("会话ID不能为空");
        }

        // 设置默认分页参数
        int actualPageNum = pageNum != null ? pageNum : 1;
        int actualPageSize = pageSize != null ? Math.min(pageSize, MAX_PAGE_SIZE) : DEFAULT_PAGE_SIZE;

        try {
            Page<ChatHistoryDO> chatHistories = chatHistoryMapper.selectPage(new Page<>(actualPageNum, actualPageSize),
                    new LambdaQueryWrapper<ChatHistoryDO>().eq(ChatHistoryDO::getUserId, userId).eq(ChatHistoryDO::getIsDeleted, false)
                            .eq(ChatHistoryDO::getSessionId, sessionId)
                            .orderByAsc(ChatHistoryDO::getCreateTime));
            return chatHistories.convert(this::buildChatHistoryResponse);
        } catch (Exception e) {
            log.error("获取会话聊天历史失败: userId={}, sessionId={}, pageNum={}, pageSize={}",
                    userId, sessionId, actualPageNum, actualPageSize, e);
            throw new RuntimeException("获取会话聊天历史失败: " + e.getMessage());
        }
    }

    /**
     * 获取用户的会话列表
     *
     * @param userId   用户ID
     * @param pageNum  当前页
     * @param pageSize 页大小
     * @return 会话列表
     */
    public Page<ChatHistoryDto.SessionResponse> getUserSessions(Integer userId, Integer pageNum, Integer pageSize) {
        // 参数校验
        if (userId == null) {
            throw new IllegalArgumentException("用户ID不能为空");
        }

        // 设置默认分页参数
        int actualPageNum = pageNum != null ? pageNum : 1;
        int actualPageSize = pageSize != null ? Math.min(pageSize, MAX_PAGE_SIZE) : DEFAULT_PAGE_SIZE;

        try {
            // 获取用户的所有会话ID
            List<String> sessionIds = chatHistoryMapper.selectList(
                            new LambdaQueryWrapper<ChatHistoryDO>().eq(ChatHistoryDO::getUserId, userId).eq(ChatHistoryDO::getIsDeleted, false))
                    .stream().map(ChatHistoryDO::getSessionId).distinct().toList();

            // 为每个会话ID创建会话响应
            List<ChatHistoryDto.SessionResponse> sessions = new ArrayList<>();
            for (String sessionId : sessionIds) {
                // 获取会话的最后一条消息
                LambdaQueryWrapper<ChatHistoryDO> queryWrapper = new LambdaQueryWrapper<ChatHistoryDO>()
                        .eq(ChatHistoryDO::getUserId, userId).eq(ChatHistoryDO::getSessionId, sessionId)
                        .eq(ChatHistoryDO::getIsDeleted, false)
                        .orderByDesc(ChatHistoryDO::getCreateTime);
                ChatHistoryDO lastMessage = chatHistoryMapper.selectOne(queryWrapper);

                if (lastMessage != null) {
                    // 获取会话的消息数量
                    Long messageCount = chatHistoryMapper.selectCount(new LambdaQueryWrapper<ChatHistoryDO>()
                            .eq(ChatHistoryDO::getUserId, userId)
                            .eq(ChatHistoryDO::getSessionId, sessionId)
                            .eq(ChatHistoryDO::getIsDeleted, false));

                    // 创建会话响应
                    ChatHistoryDto.SessionResponse session = new ChatHistoryDto.SessionResponse();
                    session.setSessionId(sessionId);
                    session.setLastMessage(lastMessage.getContent());
                    session.setLastMessageTime(lastMessage.getCreateTime());
                    session.setMessageCount(messageCount.intValue());

                    sessions.add(session);
                }
            }

            // 分页处理
            int start = (actualPageNum - 1) * actualPageSize;
            int end = Math.min((start + actualPageSize), sessions.size());

            List<ChatHistoryDto.SessionResponse> pageContent = sessions.subList(start, end);
            Page<ChatHistoryDto.SessionResponse> page = new Page<>(actualPageNum, actualPageSize);
            page.setRecords(pageContent);
            page.setTotal(sessions.size());

            return page;
        } catch (Exception e) {
            log.error("获取用户会话列表失败: userId={}, pageNum={}, pageSize={}",
                    userId, actualPageNum, actualPageSize, e);
            throw new RuntimeException("获取用户会话列表失败: " + e.getMessage());
        }
    }

    /**
     * 删除聊天记录
     *
     * @param id     聊天记录ID
     * @param userId 用户ID
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteChatHistory(Integer id, Integer userId) {
        // 检查聊天记录是否存在且属于该用户
        ChatHistoryDO chatHistoryDO = chatHistoryMapper.selectOne(
                new LambdaQueryWrapper<ChatHistoryDO>()
                        .eq(ChatHistoryDO::getId, id)
                        .eq(ChatHistoryDO::getUserId, userId)
                        .eq(ChatHistoryDO::getIsDeleted, false)
        );
        if (chatHistoryDO == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND, "聊天记录不存在或无权限访问");
        }

        // 软删除聊天记录
        chatHistoryDO.setIsDeleted(true);
        chatHistoryMapper.updateById(chatHistoryDO);

        log.info("用户 {} 删除聊天记录: {}", userId, id);
    }

    /**
     * 删除会话的所有聊天记录
     *
     * @param userId    用户ID
     * @param sessionId 会话ID
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteChatHistoryBySession(Integer userId, String sessionId) {
        // 检查会话是否存在且属于该用户
        List<ChatHistoryDO> chatHistories = chatHistoryMapper.selectList(new LambdaQueryWrapper<ChatHistoryDO>()
                .eq(ChatHistoryDO::getUserId, userId)
                .eq(ChatHistoryDO::getSessionId, sessionId)
                .eq(ChatHistoryDO::getIsDeleted, false)
        );
        if (chatHistories.isEmpty()) {
            throw new BusinessException(ErrorCode.NOT_FOUND, "会话不存在或无权限访问");
        }

        // 软删除会话的所有聊天记录
        for (ChatHistoryDO chatHistoryDO : chatHistories) {
            chatHistoryDO.setIsDeleted(true);
            chatHistoryMapper.updateById(chatHistoryDO);
        }

        log.info("用户 {} 删除会话 {} 的所有聊天记录", userId, sessionId);
    }

    /**
     * 删除用户的所有聊天记录
     *
     * @param userId 用户ID
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteAllChatHistory(Integer userId) {
        // 获取用户的所有聊天记录
        List<ChatHistoryDO> chatHistories = chatHistoryMapper.selectList(new LambdaQueryWrapper<ChatHistoryDO>()
                .eq(ChatHistoryDO::getUserId, userId).eq(ChatHistoryDO::getIsDeleted, false));

        // 软删除用户的所有聊天记录
        for (ChatHistoryDO chatHistoryDO : chatHistories) {
            chatHistoryDO.setIsDeleted(true);
            chatHistoryMapper.updateById(chatHistoryDO);
        }

        log.info("用户 {} 删除所有聊天记录", userId);
    }

    /**
     * 清除指定时间之前的聊天记录
     *
     * @param userId     用户ID
     * @param beforeTime 时间
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void clearChatHistoryBeforeTime(Integer userId, LocalDateTime beforeTime) {
        // 获取指定时间之前的所有聊天记录
        List<ChatHistoryDO> chatHistories = chatHistoryMapper.selectList(new LambdaQueryWrapper<ChatHistoryDO>()
                .eq(ChatHistoryDO::getUserId, userId)
                .eq(ChatHistoryDO::getIsDeleted, false)
                .lt(ChatHistoryDO::getCreateTime, beforeTime)
        );
        // 软删除这些聊天记录
        for (ChatHistoryDO chatHistoryDO : chatHistories) {
            chatHistoryDO.setIsDeleted(true);
            chatHistoryMapper.updateById(chatHistoryDO);
        }

        log.info("用户 {} 清除 {} 之前的所有聊天记录", userId, beforeTime);
    }

    /**
     * 获取聊天统计信息
     *
     * @param userId 用户ID
     * @return 聊天统计信息
     */
    public ChatHistoryDto.StatisticsResponse getChatStatistics(Integer userId) {
        ChatHistoryDto.StatisticsResponse response = new ChatHistoryDto.StatisticsResponse();
        List<ChatHistoryDO> list = this.list(new LambdaQueryWrapper<ChatHistoryDO>()
                .eq(ChatHistoryDO::getUserId, userId)
                .eq(ChatHistoryDO::getIsDeleted, false)
                .orderByDesc(ChatHistoryDO::getCreateTime)
        );
        if (CollectionUtils.isEmpty(list)) {
            return response;
        }
        // 获取总消息数量
        response.setTotalMessages(list.size());
        // 获取会话数量
        response.setSessionCount(list.stream().map(ChatHistoryDO::getSessionId).distinct().count());
        // 获取总token数量
        response.setTotalTokens(list.stream().map(ChatHistoryDO::getTokens).reduce(0, Integer::sum));
        // 获取最早的消息时间
        LocalDateTime firstMessageTime = list.get(list.size() - 1).getCreateTime();
        response.setFirstMessageTime(firstMessageTime);
        // 获取最晚的消息时间
        LocalDateTime lastMessageTime = list.get(0).getCreateTime();
        response.setLastMessageTime(lastMessageTime);
        return response;
    }

    /**
     * 生成会话ID
     *
     * @return 会话ID
     */
    private String generateSessionId() {
        return SESSION_PREFIX + System.currentTimeMillis() + "_" + UUID.randomUUID().toString().substring(0, 8);
    }

    /**
     * 构建聊天历史响应
     *
     * @param chatHistoryDO 聊天历史实体
     * @return 聊天历史响应
     */
    private ChatHistoryDto.ChatHistoryResponse buildChatHistoryResponse(ChatHistoryDO chatHistoryDO) {
        ChatHistoryDto.ChatHistoryResponse response = new ChatHistoryDto.ChatHistoryResponse();
        response.setId(chatHistoryDO.getId());
        response.setUserId(chatHistoryDO.getUserId());
        response.setSessionId(chatHistoryDO.getSessionId());
        response.setRole(chatHistoryDO.getRole());
        response.setContent(chatHistoryDO.getContent());
        response.setModel(chatHistoryDO.getModel());
        response.setTokens(chatHistoryDO.getTokens());
        response.setCreatedAt(chatHistoryDO.getCreateTime());
        return response;
    }
}